home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-23 | 15.7 KB | 551 lines | [TEXT/CWIE] |
- // FinderFun.cp
- #include "FinderFun.h"
-
- #define kIconSize 1024 // The size of an icl8
- #define kMaskSize 256 // The size of an ICN# (icon and mask, each 128)
- #define kSmallIconSize 256 // The size of an ics8
- #define kSmallMaskSize 64 // The size of an ics# (icon and mask, each 32)
-
- extern long gNumItems;
- extern Handle gIcons[];
- extern Handle gMasks[];
- extern Point gPositions[];
- extern Rect gWindowRect;
- extern long gWindowView;
-
- //----------------------------------------------------------------------------------------
- // FindPSNbyTypeAndSig:
- //
- // Find the PSN of some process, given its type and creator
- //----------------------------------------------------------------------------------------
- void FindPSNbyTypeAndSig(ProcessSerialNumber* psn, OSType type, OSType sig)
- {
- ProcessInfoRec theProc;
-
- //
- // Start out with kNoProcess
- //
- psn->highLongOfPSN = 0;
- psn->lowLongOfPSN = kNoProcess;
-
- //
- // Initialize fields in the ProcessInfoRec,
- // or we'll have memory hits in random locations
- //
- theProc.processInfoLength = sizeof( ProcessInfoRec );
- theProc.processName = nil;
- theProc.processAppSpec = nil;
- theProc.processLocation = nil;
-
- while(true)
- {
- OSErr theErr;
-
- //
- // Keep looking for the Finder until we find it
- //
- FailErr(GetNextProcess(psn));
- if( (psn->highLongOfPSN == 0) && (psn->lowLongOfPSN == kNoProcess) )
- Throw(procNotFound);
-
- //
- // Is the current process the one we're looking for?
- //
- FailErr(GetProcessInformation(psn, &theProc));
- if( (theProc.processType == type ) && (theProc.processSignature == sig) )
- break;
- }
- } // FindPSNbyTypeAndSig
-
- //----------------------------------------------------------------------------------------
- // GetAddressOfFinder:
- //
- // Generate an address for the Finder on this machine
- //----------------------------------------------------------------------------------------
- TDescriptor GetAddressOfFinder()
- {
- ProcessSerialNumber finderPSN;
- TDescriptor finderAddressDescriptor;
-
- //
- // Find the Finder's PSN
- //
- FindPSNbyTypeAndSig(&finderPSN, 'FNDR', 'MACS');
-
- //
- // Copy the target ID into a descriptor
- //
- finderAddressDescriptor.MakeProcessSerialNumber(finderPSN);
-
- return finderAddressDescriptor;
- } // GetAddressOfFinder
-
- //----------------------------------------------------------------------------------------
- // MakeSpecifierForFrontWindow
- //----------------------------------------------------------------------------------------
- TDescriptor MakeSpecifierForFrontWindow()
- {
- TDescriptor nullDescriptor;
-
- return MakeSpecifierForIndexedItem(cWindow, 1, nullDescriptor);
- }
-
- //----------------------------------------------------------------------------------------
- // MakeSpecifierForIndexedItem
- //----------------------------------------------------------------------------------------
- TDescriptor MakeSpecifierForIndexedItem(DescType desiredClass, long index, TDescriptor ofSpecifier)
- {
- TDescriptor resultSpecifier;
- TDescriptor keyData;
-
- //
- // Make a descriptor whose type is 'typeLongInteger' and whose
- // contents is the index passed in.
- //
- keyData.MakeLong(index);
-
- //
- // Make an object specifier for "<<class desiredClass>> index of <ofSpecifier>".
- // The object specifier will contain the following:
- //
- // Desired class: desiredClass The class of the object being referenced;
- // examples include cWindow, cObject, cDisk,
- // cAliasFile, and many others
- //
- // Container: ofSpecifier Object specifiers are defined recursively
- //
- // Key form: formAbsolutePosition This indicates that we are accessing the
- // 'index'th item of the container. Another
- // choice would be formName, in which case
- // the key data would contain the name of the
- // object being referenced.
- //
- // Key data: typeLongInteger / formAbsolutePosition implies that the key data
- // 'index' will be an integer
- //
- // We pass 'false' to MakeObjectSpecifier, so our inputs are not disposed
- // (we want to keep 'ofSpecifier' around). Because we didn't ask MakeObjectSpecifier
- // to delete our inputs, we'll have to delete the key data ourselves
- //
- resultSpecifier.MakeObjectSpecifier(desiredClass, ofSpecifier, formAbsolutePosition, keyData, false);
- keyData.Dispose();
-
- return resultSpecifier;
- } // MakeSpecifierForSelection
-
- //----------------------------------------------------------------------------------------
- // MakeSpecifierForPropertyOfSpecifier:
- //
- // This function makes an object specifier for "property of <<specifier provided>>"
- //----------------------------------------------------------------------------------------
- TDescriptor MakeSpecifierForPropertyOfSpecifier(DescType property, TDescriptor ofSpecifier)
- {
- TDescriptor specifier;
- TDescriptor keyData;
- OSErr err = noErr;
-
- //
- // Make a descriptor whose type is 'typeType', and whose
- // contents are the property passed into this function.
- //
- keyData.MakeDescType(property);
-
- Try
- {
- //
- // The next object specifier we make also specifies a property, so it
- // will look very similar to the one we built above:
- //
- // Desired class cProperty Required to specify a property.
- //
- // Container "ofSpecifier" We are making a specifier for
- // "property of <ofSpecifier>", so clearly
- // our container must be the
- // object specifier passed in.
- //
- // Key form: formPropertyID Required to specify a property.
- //
- // Key data typeType / As before, the key data descriptor
- // property is typeType, and contains the property ID
- // that we wish to specify.
- //
- // This time we pass 'false' to MakeObjectSpecifier so that it will NOT dispose
- // of its inputs when it is done. Doing this leaves the keyData and ofSpecifier
- // descriptors intact; we dispose of the key data, but leave the specifier that
- // was passed into this function the responsibility of the caller.
- //
- specifier.MakeObjectSpecifier(cProperty, ofSpecifier, formPropertyID, keyData, false);
- keyData.Dispose();
- }
- Catch(err)
- {
- //
- // Note that 'MakeObjectSpecifier' might fail (out of memory, for example),
- // so we must catch failures to dispose of the key data descriptor if necessary.
- //
- keyData.Dispose();
- Throw(err);
- }
-
- return specifier;
- } // MakeSpecifierForPropertyOfSpecifier
-
- //----------------------------------------------------------------------------------------
- // CountItemsInContainer
- //
- // Returns the number of items of class 'desiredClass' inside the specified
- // container. The target application is specified in the parameter list.
- //----------------------------------------------------------------------------------------
- long CountItemsInContainer(DescType desiredClass, TDescriptor inContainer, TDescriptor target)
- {
- TAEvent ae;
- TAEvent reply;
- TDescriptor keyData;
- OSErr err = noErr;
- long theCount = 0;
-
- Try
- {
- //
- // Make a "Count elements" event
- //
- ae.MakeAppleEvent(kAECoreSuite, kAECountElements, target);
-
- //
- // Put the direct object specifier into the direct object of our event
- //
- ae.PutDescriptor(keyDirectObject, inContainer);
-
- //
- // Specify the class of things we want to count
- //
- keyData.MakeDescType(desiredClass);
- ae.PutDescriptor(keyAEObjectClass, keyData);
- keyData.Dispose();
-
- //
- // Ask the question. kAEWaitReply without filter procs is evil.
- //
- ae.Send(&reply, kAEWaitReply);
-
- //
- // Extract the result out of the reply
- //
- theCount = reply.GetLongParameter(keyAEResult);
- }
- Catch(err)
- {
- //
- // Any of a number of routines that we call above could
- // fail; if they do, we need to dispose of any object
- // that we created.
- //
- ae.Dispose();
- reply.Dispose();
- keyData.Dispose();
-
- Throw(err);
- }
-
- return theCount;
- } // CountItemsInContainer
-
- void GetFrontWindowInfo(long *numItems, Point *windPos, Rect *windRect, long *viewType)
- {
- TDescriptor target;
- TDescriptor frontWindowSpecifier;
- TDescriptor finderViewPrefsSpecifier;
- TDescriptor finderViewPrefs;
- TDescriptor positionOfFrontWindowSpecifier;
- TDescriptor positionOfFrontWindow;
- TDescriptor boundsOfFrontWindowSpecifier;
- TDescriptor boundsOfFrontWindow;
- TDescriptor viewOfFrontWindowSpecifier;
- TDescriptor viewOfFrontWindow;
- TAEvent ae;
- TAEvent reply;
- OSErr err = noErr;
-
- Try
- {
- //
- // Make the address of the finder, and an object specifier to
- // the frontmost window. We will use these descriptors a number
- // of times.
- //
- target = GetAddressOfFinder();
- frontWindowSpecifier = MakeSpecifierForFrontWindow();
-
- //
- // Make a "GetData" event
- //
- ae.MakeAppleEvent(kAECoreSuite, kAEGetData, target);
-
- //
- // Ask the Finder how many items are in the front window
- //
- *numItems = CountItemsInContainer(cObject, frontWindowSpecifier, target);
-
- // Ask the Finder about its view preferences
- // !!!
-
- //
- // Get the position of the front window
- //
- positionOfFrontWindowSpecifier = MakeSpecifierForPropertyOfSpecifier(pPosition, frontWindowSpecifier);
- ae.PutDescriptor(keyDirectObject, positionOfFrontWindowSpecifier);
- positionOfFrontWindowSpecifier.Dispose();
-
- //
- // See notes on waitreply, elsewhere
- //
- ae.Send(&reply, kAEWaitReply);
-
- // Get the position out of the reply
- positionOfFrontWindow = reply.GetDescriptor(keyAEResult);
- *windPos = positionOfFrontWindow.GetPoint();
- positionOfFrontWindow.Dispose();
-
- //
- // Get the bounds of the front window
- //
- boundsOfFrontWindowSpecifier = MakeSpecifierForPropertyOfSpecifier(keyAEBounds, frontWindowSpecifier);
- ae.PutDescriptor(keyDirectObject, boundsOfFrontWindowSpecifier);
- boundsOfFrontWindowSpecifier.Dispose();
-
- //
- // See notes on waitreply, elsewhere
- //
- ae.Send(&reply, kAEWaitReply);
-
- // Get the bounds out of the reply
- boundsOfFrontWindow = reply.GetDescriptor(keyAEResult);
- *windRect = boundsOfFrontWindow.GetRect();
- boundsOfFrontWindow.Dispose();
-
- // Calculate the real rect, accounting for scrollbars and disk info
- windRect->right -= 15;
- windRect->bottom -= 15;
- windRect->top += 20;
-
- //
- // Get the view of the front window
- //
- viewOfFrontWindowSpecifier = MakeSpecifierForPropertyOfSpecifier(pView, frontWindowSpecifier);
- ae.PutDescriptor(keyDirectObject, viewOfFrontWindowSpecifier);
- viewOfFrontWindowSpecifier.Dispose();
-
- //
- // See notes on waitreply, elsewhere
- //
- ae.Send(&reply, kAEWaitReply);
-
- // Get the view out of the reply
- viewOfFrontWindow = reply.GetDescriptor(keyAEResult);
- *viewType = viewOfFrontWindow.GetEnumeration();
- viewOfFrontWindow.Dispose();
-
- target.Dispose();
- frontWindowSpecifier.Dispose();
- }
- Catch(err)
- {
- //
- // Any of a number of routines that we call above could
- // fail; if they do, we need to dispose of any object
- // that we created.
- //
- // Hah! not really doing it, am I? dkj
- target.Dispose();
- frontWindowSpecifier.Dispose();
-
- Throw(err);
- }
- }
-
- OSErr GetFinderItemInfo(short itemNum, Handle *theBits, Handle *theMaskBits, Point *position)
- {
- TDescriptor target;
- TDescriptor frontWindowSpecifier;
- TDescriptor iconFamilyForItem;
- TDescriptor itemNOfFrontWindowSpecifier;
- TDescriptor iconOfItemNSpecifier;
- TDescriptor positionOfItemNSpecifier;
- TDescriptor positionOfItem;
- TDescriptor someBits;
- TDescriptor someMaskBits;
- TAEvent ae;
- TAEvent reply;
- long count = 0;
- OSErr err = noErr;
- Point localPosition;
-
- Try
- {
- //
- // Make the address of the finder, and an object specifier to
- // the frontmost window. We will use these descriptors a number
- // of times.
- //
- target = GetAddressOfFinder();
- frontWindowSpecifier = MakeSpecifierForFrontWindow();
-
- //
- // Get an icon family for the first item in the frontmost window
- // and save it away
- //
- ae.MakeAppleEvent(kAECoreSuite, kAEGetData, target);
-
- //
- // Set the direct object for this event to 'icon of item 1 of frontWindowSpecifier'
- //
- itemNOfFrontWindowSpecifier = MakeSpecifierForIndexedItem(cObject, itemNum, frontWindowSpecifier);
- iconOfItemNSpecifier = MakeSpecifierForPropertyOfSpecifier(pIconBitmap, itemNOfFrontWindowSpecifier);
- ae.PutDescriptor(keyDirectObject, iconOfItemNSpecifier);
- iconOfItemNSpecifier.Dispose();
-
- //
- // See notes on waitreply, elsewhere
- //
- ae.Send(&reply, kAEWaitReply);
-
- //
- // Snarf the icon family out of the reply, and make it an AERecord
- //
- iconFamilyForItem = reply.GetDescriptor(keyAEResult);
- iconFamilyForItem.CoerceInPlace(typeAERecord);
-
- // Get the appropriate bitmaps
- if(gWindowView == pIconBitmap)
- {
- // Try to snarf the icl8 from the family
- someBits = iconFamilyForItem.GetOptionalParameter(key8BitIcon);
- if(!someBits.IsNullDescriptor())
- {
- HLock(*theBits);
- someBits.GetBlock(**theBits, kIconSize, type8BitIcon);
- HUnlock(*theBits);
- }
- else // Ack! no icl8, use the regular ICN# (signaled by making the handle nil)
- {
- DisposeHandle(*theBits);
- *theBits = nil;
- }
-
- // Snarf the Mask (really Icon and Mask) from the family
- someMaskBits = iconFamilyForItem.GetOptionalParameter(keyIconAndMask);
- if(someMaskBits.IsNullDescriptor()) // Ack! no ICN#, bail out!
- return -1;
- HLock(*theMaskBits);
- someMaskBits.GetBlock(**theMaskBits, kMaskSize, typeIconAndMask);
- HUnlock(*theMaskBits);
- }
- else if(gWindowView == pSmallIcon)
- {
- // Try to snarf the ics8 from the family
- someBits = iconFamilyForItem.GetOptionalParameter(keySmall8BitIcon);
- if(!someBits.IsNullDescriptor())
- {
- HLock(*theBits);
- someBits.GetBlock(**theBits, kSmallIconSize, typeSmall8BitIcon);
- HUnlock(*theBits);
- }
- else // Ack! no ics8, use the regular ics# (signaled by making the handle nil)
- {
- DisposeHandle(*theBits);
- *theBits = nil;
- }
-
- // Snarf the Mask (really Icon and Mask) from the family
- someMaskBits = iconFamilyForItem.GetOptionalParameter(keySmallIconAndMask);
- if(someMaskBits.IsNullDescriptor()) // Ack! no ics#, bail out!
- return -1;
- HLock(*theMaskBits);
- someMaskBits.GetBlock(**theMaskBits, kSmallMaskSize, typeSmallIconAndMask);
- HUnlock(*theMaskBits);
- }
- else return -1;
-
- // Clean up icon stuff
- someBits.Dispose();
- someMaskBits.Dispose();
- iconFamilyForItem.Dispose();
-
-
- // Now get the position for the item
- positionOfItemNSpecifier = MakeSpecifierForPropertyOfSpecifier(pPosition, itemNOfFrontWindowSpecifier);
- ae.PutDescriptor(keyDirectObject, positionOfItemNSpecifier);
- positionOfItemNSpecifier.Dispose();
-
- //
- // See notes on waitreply, elsewhere
- //
- ae.Send(&reply, kAEWaitReply);
-
- // Get the position out of the reply
- positionOfItem = reply.GetDescriptor(keyAEResult);
- localPosition = positionOfItem.GetPoint();
- *position = localPosition;
-
- // Cleanup
- positionOfItem.Dispose();
- positionOfItemNSpecifier.Dispose();
- itemNOfFrontWindowSpecifier.Dispose();
- target.Dispose();
- frontWindowSpecifier.Dispose();
- }
- Catch(err)
- {
- //
- // Any of a number of routines that we call above could
- // fail; if they do, we need to dispose of any object
- // that we created.
- //
- // Hah! not really doing it, am I? dkj
- target.Dispose();
- frontWindowSpecifier.Dispose();
-
- Throw(err);
- }
- return noErr;
- }
-
- OSErr GatherFinderInfo(short maxItems)
- {
- short cnt, err;
- Point windowPosition;
-
- // get the position of, and number of items in, the front window
- GetFrontWindowInfo(&gNumItems, &windowPosition, &gWindowRect, &gWindowView);
- if(gNumItems > maxItems)
- return -1;
-
- for(cnt = 0; cnt < gNumItems; cnt++)
- {
- if(gWindowView == pIconBitmap)
- {
- gIcons[cnt] = NewHandle(kIconSize);
- gMasks[cnt] = NewHandle(kMaskSize);
- }
- else if(gWindowView == pSmallIcon)
- {
- gIcons[cnt] = NewHandle(kSmallIconSize);
- gMasks[cnt] = NewHandle(kSmallMaskSize);
- }
- else return -1;
-
- if(gIcons[cnt] == nil || gMasks[cnt] == nil)
- return -1; // Oooh, no cleaning up
-
- // Get each item's icon and position
- err = GetFinderItemInfo(cnt + 1, &gIcons[cnt], &gMasks[cnt], &gPositions[cnt]);
- if(err) return err;
-
- AddPt(windowPosition, &gPositions[cnt]);
- }
- return noErr;
- }
-
-
-
-